#include <iostream>
#include <assert.h>
#include <vector>
#include <time.h>
using namespace std;
namespace Aurora
{
    template<class K,class V>
    struct AVLTreeNode
    {
        // 需要parent指针，后续更新平衡因⼦可以看到
        pair<K,V> _kv;
        AVLTreeNode<K,V>* _left;
        AVLTreeNode<K,V>* _right;
        AVLTreeNode<K,V>* _parent;
        int _bf;// balance factor
        AVLTreeNode(const pair<K,V>& kv)
            :_kv(kv)
            ,_left(nullptr)
            ,_right(nullptr)
            ,_parent(nullptr)
            ,_bf(0)
        {}
    };
    template<class K,class V>
    class AVLTree
    {
        typedef AVLTreeNode<K,V> Node;
    public:
        bool Insert(const pair<K,V>& kv)
        {
            if(_root == nullptr)
            {
                _root = new Node(kv);
                return true;
            }
            Node* cur = _root;
            Node* parent = nullptr;
            while(cur)
            {
                if(cur->_kv.first < kv.first)
                {
                    parent = cur;
                    cur = cur->_right;
                }
                else if(cur->_kv.first > kv.first)
                {
                    parent = cur;
                    cur = cur->_left;
                }
                else if(cur->_kv.first == kv.first)
                {
                    return false;
                }
            }
            cur = new Node(kv);
            if(parent->_kv.first > kv.first)
            {
                parent->_left = cur;
            }
            else if(parent->_kv.first < kv.first)
            {
                parent->_right = cur;
            }
            //当前结点跟父结点链接在一起
            cur->_parent = parent;
            //更新平衡因子
            while(parent)
            {
                if(parent->_left == cur)
                {
                    parent->_bf--;
                }
                else if(parent->_right == cur)
                {
                    parent->_bf++;
                }
                if(parent->_bf == 0)
                {
                    break;
                }
                else if(parent->_bf == 1 || parent->_bf == -1)
                {
                    cur = parent;
                    parent= parent->_parent;
                }
                else if(parent->_bf == 2 || parent->_bf == -2)
                {
                    //旋转
                    if(parent->_bf == -2 && cur->_bf == -1 )
                    {
                        //右单旋
                        RotateR(parent);
                    }
                    else if(parent->_bf == 2 && cur->_bf == 1)
                    {
                        //左单旋
                        RotateL(parent);
                    }
                    else if(parent->_bf == -2 && cur->_bf == 1)
                    {
                        //左右双旋
                        RotateLR(parent);
                    }
                    else if(parent->_bf == 2 && cur->_bf == -1)
                    {
                        //右左双旋
                        RotateRL(parent);
                    }
                    else
                    {
                        assert(false);
                    }
                    break;
                }
                else
                {
                    assert(false);
                }
            }
            return true;
        }
        //AVL树的查找
        Node* Find(const K& key)
        {
            Node* cur = _root;
            while(cur)
            {
                if(cur->_kv.first > key)
                {
                    cur = cur->_left;
                }
                else if(cur->_kv.first < key)
                {
                    cur = cur->_right;
                }
                else if(cur->_kv.first == key)
                {
                    return cur;
                }
            }
            return nullptr;
        }
        //中序遍历
        void InOrder()
        {
            _InOrder(_root);
        }
        //检查该树是否是AVL树
        bool IsBalanceTree()
        {
            return _IsBalanceTree(_root);
        }
        //树的高度
        int Height()
        {
            return _Height(_root);
        }
        //Size()
        int Size()
        {
            return _Size(_root);
        }
    private:
        //_Size
        int _Size(Node* root)
        {
            if(root == nullptr) return 0;
            return 1 + _Size(root->_left) + _Size(root->_right);
        }
        //检查该树是否是AVL树
        bool _IsBalanceTree(Node* root)
        {
            //空树也是AVL树
            if(root == nullptr) return true;
            //计算右子树的高度
            int rightHight = _Height(root->_right);
            //计算左子树的高度
            int leftHight = _Height(root->_left);
            //右子树的高度减去左子树的高度,算出高度差
            int diff = rightHight - leftHight;
            //判断高度是否合理
            if(abs(diff) >= 2)
            {
                cout << root->_kv.first << "高度差异常" << endl;
                return false;
            }
            if(root->_bf != diff)
            {
                cout << root->_kv.first << "平衡因子异常" << endl;
                return false;
            }
            return _IsBalanceTree(root->_left) && _IsBalanceTree(root->_right);
        }
        //求树的高度
        int _Height(Node* root)
        {
            if(root == nullptr) return 0;
            int leftHeight = _Height(root->_left);
            int rightHeight = _Height(root->_right);
            return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
        }
        //右单旋
        void RotateR(Node* parent)
        {
            //找到要调整的节点
            Node* subL = parent->_left;
            Node* subLR = subL->_right;
            //修改指向
            parent->_left = subLR;
            subL->_right = parent;
            //保存parent的父节点
            Node* pphead = parent->_parent;
            //修改节点中_parent的指向
            if(subLR)
                subLR->_parent = parent;
            parent->_parent = subL;
            //更新根节点的父节点
            //if(pphead == nullptr)
            if(parent == _root)
            {
                //直接更新_root节点
                _root = subL;
                //将根节点的_parent的节点置为空
                subL->_parent = nullptr;
            }
            else
            {
                if(pphead->_left == parent)
                {
                    pphead->_left = subL;
                }
                else if(pphead->_right == parent)
                {
                    pphead->_right = subL;
                }
                //更新根节点的_parent
                subL->_parent = pphead;
            }
            //更新平衡因子
            parent->_bf = subL->_bf = 0;
        }
        //左单旋
        void RotateL(Node* parent)
        {
            //确定要调整的节点
            Node* subR = parent->_right;
            Node* subRL = subR->_left;
            //改变节点关系
            parent->_right = subRL;
            subR->_left = parent;
            //保存parent的父节点
            Node* pphead = parent->_parent;
            //改变每个节点的_parent
            if(subRL)
                subRL->_parent = parent;
            parent->_parent = subR;
            //if(pphead == nullptr)
            if(parent == _root)
            {
                //更新根节点
                _root = subR;
                //更新根节点的父节点
                subR->_parent = nullptr;
            }
            else
            {
                //将根节点和根节点的父节点链接
                if(pphead->_left == parent)
                {
                    pphead->_left = subR;
                }
                else if(pphead->_right == parent)
                {
                    pphead->_right = subR;
                }
                //更新根节点的_parent
                subR->_parent = pphead;
            }
            //更新平衡因子
            parent->_bf = subR->_bf = 0;
        }
        //左右双旋
        void RotateLR(Node* parent)
        {
            //保存要调整的节点,方便更新平衡因子
            Node* subL = parent->_left;
            Node* subLR = subL->_right;
            //记录subLR节点的平衡因子
            int bf = subLR->_bf;
            //首先对subL进行左单旋
            RotateL(parent->_left);
            //再对parent进行右旋转
            RotateR(parent);
            //更新平衡因子
            if(bf == -1)
            {
                subLR->_bf = 0;
                subL->_bf = 0;
                parent->_bf = 1;
            }
            else if(bf == 1)
            {
                subLR->_bf = 0;
                subL->_bf = -1;
                parent = 0;
            }
            else if(bf == 0)
            {
                subLR->_bf = 0;
                subL->_bf = 0;
                parent = 0;
            }
            else
            {
                assert(false);
            }
        }
        //右左双旋
        void RotateRL(Node* parent)
        {
            //保留节点,方便更新平衡因子
            Node* subR = parent->_right;
            Node* subRL = subR->_left;
            //保留subRL中的平衡因子
            int bf = subRL->_bf;
            //对subR进行右单旋
            RotateR(parent->_right);
            //对parent进行左单旋
            RotateL(parent);
            //更新平衡因子
            if(bf == 1)
            {
                parent->_bf = -1;
                subR->_bf = 0;
                subRL->_bf = 0;
            }
            else if(bf == -1)
            {
                parent->_bf = 0;
                subR->_bf = 1;
                subRL->_bf = 0;
            }
            else if(bf == 0)
            {
                parent->_bf = 0;
                subR->_bf = 0;
                subRL->_bf = 0;
            }
            else
            {
                assert(false);
            }
        }
        //AVL树的遍历
        void _InOrder(Node* root)
        {
            if(root == nullptr) return;
            _InOrder(root->_left);
            cout << root->_kv.first << ":" << root->_kv.second << endl;
            _InOrder(root->_right);
        }
        Node* _root = nullptr;
    };
}
//测试代码
void TestAVLTree1()
{
    Aurora::AVLTree<int,int> t;
    //常规测试用例
    //int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
    //特殊带有双旋场景测试用例
    int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
    //插入
    for(const auto& e : a)
    {
        if(e == 6)
        {
            int x = 0;
        }
        t.Insert({e,e});
    }
    //遍历
    t.InOrder();
    cout << t.IsBalanceTree() << endl;
}
//插入一堆随机值,测试平衡,顺便测试高度,性能等
void TestAVLTree2()
{
    const int N = 1000000;
    vector<int> v;
    v.reserve(N);
    srand(time(0));
    for (size_t i = 0; i < N; i++)
    {
        v.push_back(rand() + i);
    }
    size_t begin2 = clock();
    Aurora::AVLTree<int,int> t;
    for(const auto& e : v)
    {
        t.Insert(make_pair(e,e));
    }
    size_t end2 = clock();

    cout << "Insert:" << end2 - begin2 << endl;
    cout << t.IsBalanceTree() << endl;
    cout << "Height:" << t.Height() << endl;
    cout << "Size:" << t.Size() << endl;
    size_t begin1 = clock();
    // 确定在的值
    /*for (auto e : v) 
    {
    t.Find(e);
    }*/
    // 随机值
    for (size_t i = 0; i < N; i++)
    {
        t.Find((rand() + i));
    }
    size_t end1 = clock();
    cout << "Find:" << end1 - begin1 << endl;
}